package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author atguigu-mqx
 */
@Service
public class CartServiceImpl implements CartService {

    //  通常服务层，调用mapper 层！ 但是，在此不用！
    //  我们直接将数据添加到缓存！
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Override
    public void addToCart(Long skuId, String userId, Integer skuNum) {
        /**
         * 添加购物车的业务逻辑！
         * 1.   先判断购物车中是否有该商品！
         *  true:
         *      skuNum + skuNum;
         *      每次添加商品的时候都需要做一个选中状态！ "默认被选中"！
         *
         *  false:
         *      直接写入购物车！
         *
         */
        //  缓存要使用哪种数据类型存储！ hash  hset key field value  hget key field;
        //  key: user:userId:cart   field = skuId   value = 购物项 统一封装到cartInfo 对象中！
        //  cartKey = user:userId:cart
        String cartKey = getCartKey(userId);
        //  获取到购物车key 对应的数据！ hget key field
        CartInfo cartInfoExist = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
        //        Boolean flag = this.redisTemplate.opsForHash().hasKey(cartKey, skuId.toString());
        //        CartInfo cartInfo1 = (CartInfo) this.redisTemplate.boundHashOps(cartKey).get(skuId.toString());
        //        Boolean result = this.redisTemplate.boundHashOps(cartKey).hasKey(skuId.toString());
        //        if (result){
        //            //  有数据;
        //        }else {
        //            //  没有数据
        //        }
        //        if (flag){
        //            //  有；
        //        }else {
        //            //  没有；
        //        }
        //  判断
        if (cartInfoExist!=null){
            //  说明购物车中有这个商品
            //  数量相加：
            cartInfoExist.setSkuNum(cartInfoExist.getSkuNum()+skuNum);
            //  选中状态
            cartInfoExist.setIsChecked(1);
            //  重新赋值商品的试试价格：
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            //  展示购物车的时候，按照商品的更新时间进行排序！
            cartInfoExist.setUpdateTime(new Date()); // 按照京东更新时间排序， 苏宁按照创建时间排序
            //            //  hset key field value
            //            this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        }else {
            //  说明购物车中没有这个商品
            //  获取商品的基本信息： 购物车数据来自于商品详情 -- 商品详情详情数据 来自于 service-product
            SkuInfo skuInfo = this.productFeignClient.getSkuInfo(skuId);

            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuPrice(skuInfo.getPrice());
            cartInfo.setCartPrice(skuInfo.getPrice());
            cartInfo.setSkuNum(skuNum);
            cartInfo.setSkuId(skuId);
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfo.setSkuName(skuInfo.getSkuName());
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());

            //  需要将cartInfo 添加到缓存！
//          //  hset key field value
//          this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);
            cartInfoExist = cartInfo;
        }
        //  hset key field value
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        //  暂时不写缓存的过期时间了！
    }

    /**
     * 查看购物车
     * @param userId
     * @param userTempId
     * @return
     */
    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {

        /*
        合并场景：
            case1: 有userId , 没有userTempId    只需要返回 loginCartList
            case2: 没有userId, 有userTempId    只需要返回 noLoginCartList
            case3: 有userId, 有userTempId 此时需要合并！

            首先：获取到未登录购物车集合数据！
                判断集合数据是否为空
                    true:  不合并！
                    false:  才有可能合并
                            userId 不为空！
                                才会发生合并！
         */
        //  声明一个集合来存储未登录购物车数据！
        List<CartInfo> noLoginCartInfoList = new ArrayList<>();
        //  case2 : 没有userId, 有userTempId  只需要返回 noLoginCartList
        //  未登录：
        if (!StringUtils.isEmpty(userTempId)){
            noLoginCartInfoList = this.redisTemplate.opsForHash().values(this.getCartKey(userTempId));
        }
        //  添加一个判断： 用户未登录！ 此时只存在临时用户Id
        if(StringUtils.isEmpty(userId)){
            //  判断临时购物车数据不为空！则直接返回数据！
            if (!CollectionUtils.isEmpty(noLoginCartInfoList)){
                noLoginCartInfoList.sort((o1,o2)->{
                    //  工具类比较时间：
                    return DateUtil.truncatedCompareTo(o2.getUpdateTime(),o1.getUpdateTime(), Calendar.SECOND);
                });
            }
            //  返回未登录购物车集合数据！
            return noLoginCartInfoList;
        }
        //  -------------------case2 end -----------------------
         /*
        demo:
            登录：
                17  1
                18  1

            未登录：
                17  1
                18  1
                19  2

            合并：
                17  2
                18  2
                19  2
         */
        //  case1: 有userId , 没有userTempId  case3: 有userId, 有userTempId 此时需要合并！
        //  case1,case3 用户Id 存在！
        //  声明一个集合来存储 登录的购物车集合数据！
        List<CartInfo> loginCartInfoList = new ArrayList<>();
        //  先获取到登录购物车数据的key
        String cartKey = this.getCartKey(userId);
        //  获取所有的数据！
        //  BoundHashOperations<H, HK, HV> hset key field value  hget key field
        BoundHashOperations<String,String,CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);

        //  判断 : 说明未登录购物车有数据  有userId ,  有userTempId 临时购物车集合中有数据！才会合并！
        if (!CollectionUtils.isEmpty(noLoginCartInfoList)){
            //  此时才会发生合并购物车！
            //  合并的条件： 必须是skuId 相同！
            noLoginCartInfoList.stream().forEach(cartInfo -> {
                //  登录的skuId 与未登录的skuId 相等  17  18
                if (boundHashOperations.hasKey(cartInfo.getSkuId().toString())){
                    //   hget key field
                    CartInfo loginCartInfo = boundHashOperations.get(cartInfo.getSkuId().toString());
                    loginCartInfo.setSkuNum(loginCartInfo.getSkuNum()+cartInfo.getSkuNum());
                    loginCartInfo.setUpdateTime(new Date());
                    //  再次确认查询 一次商品的最新价格：
                    loginCartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));

                    //  判断选中状态：
                    if (cartInfo.getIsChecked().intValue()==1){
                        if (loginCartInfo.getIsChecked().intValue()==0){
                            loginCartInfo.setIsChecked(1);
                        }
                        //  暴力赋值！
                        loginCartInfo.setIsChecked(1);
                    }
                    //  写回缓存！
                    boundHashOperations.put(cartInfo.getSkuId().toString(),loginCartInfo);
                }else {
                    //  19
                    cartInfo.setUserId(userId);
                    cartInfo.setCreateTime(new Date());
                    cartInfo.setUpdateTime(new Date());
                    //  新增到缓存中！
                    boundHashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
                }
            });
            //  删除未登录购物车数据集合：
            this.redisTemplate.delete(this.getCartKey(userTempId));
        }

        //  统一查询一下最终的结果  17 ，18 ，19 hvals key;
        //  loginCartInfoList = this.redisTemplate.opsForHash().values(this.getCartKey(userId));
        loginCartInfoList = boundHashOperations.values();
        //  判断
        if (CollectionUtils.isEmpty(loginCartInfoList)){
            return new ArrayList<>();
        }
        //  还需要设置排序：
        loginCartInfoList.sort((o1, o2) -> {
            //  比较数据
            return DateUtil.truncatedCompareTo(o2.getUpdateTime(),o1.getUpdateTime(), Calendar.SECOND);
        });
        //  将数据集合返回！
        return loginCartInfoList;
    }

    @Override
    public void checkCart(String userId, Long skuId, Integer isChecked) {
        //  修改缓存！
        //  获取到缓存的key
        String cartKey = this.getCartKey(userId);
        CartInfo cartInfo = (CartInfo) this.redisTemplate.boundHashOps(cartKey).get(skuId.toString());
        //  判断是否存在
        if (cartInfo!=null){
            //  修改选中状态数据
            cartInfo.setIsChecked(isChecked);
            //  再次放入缓存！
            this.redisTemplate.boundHashOps(cartKey).put(skuId.toString(),cartInfo);
        }
    }

    @Override
    public void deleteCart(String userId, Long skuId) {
        //  获取到缓存的key hdel user:1:cart 21
        String cartKey = this.getCartKey(userId);

        //  删除数据 hdel user:1:cart 21 暴力删除！
        //  this.redisTemplate.boundHashOps(cartKey).delete(skuId.toString());
        Boolean flag = this.redisTemplate.boundHashOps(cartKey).hasKey(skuId.toString());
        if (flag){
            this.redisTemplate.boundHashOps(cartKey).delete(skuId.toString());
        }

    }

    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        //  购物车中的数据都是在缓存中存储的！
        //  根据用户Id 来获取到缓存的key
        String cartKey = this.getCartKey(userId);
        //  hvals user:userId:cart
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  判断
        if (CollectionUtils.isEmpty(cartInfoList)) {
            return new ArrayList<>();
        }

        //        List<CartInfo> cartInfoLists = new ArrayList<>();
        //        //  购物车中有数据！
        //        for (CartInfo cartInfo : cartInfoList) {
        //            //  判断
        //            if(cartInfo.getIsChecked().intValue()==1){
        //                //  将选中的商品保存起来！
        //                cartInfoLists.add(cartInfo);
        //            }
        //        }
        //  拉姆达表达式好处！
        List<CartInfo> cartInfoLists = cartInfoList.stream().filter(cartInfo -> {
            //  查询最新价格：
            cartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));
            //  获取符合条件的数据！
            return cartInfo.getIsChecked().intValue() == 1;
        }).collect(Collectors.toList());

        //  返回数据！
        return cartInfoLists;
    }

    @Override
    public void delCart(String userId) {
        //  先组成购物车的key！
        String cartKey = this.getCartKey(userId);
        //  获取购物车中的所有数据！ hvals
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        if (!CollectionUtils.isEmpty(cartInfoList)){
            //  删除被选中的购物项：
            for (CartInfo cartInfo : cartInfoList) {
                if (cartInfo.getIsChecked().intValue()==1){
                    this.redisTemplate.opsForHash().delete(cartKey,cartInfo.getSkuId().toString());
                }
            }
        }


    }

    /**
     * 获取缓存的key！
     * @param userId
     * @return
     */
    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX+userId+RedisConst.USER_CART_KEY_SUFFIX;
    }
}
